#pragma once

#if defined(_WIN32)
#if defined(EXPORTING_Exception)
#define Utility_Exception_DECLSPEC __declspec (dllexport)
#else
#define Utility_Exception_DECLSPEC __declspec (dllimport)
#endif
#else  // non windows
#define Utility_Exception_DECLSPEC
#endif

#include <exception>
#include <istream>
#include <ostream>
#include <sstream>
#include <string>

namespace SG::Utility
{
    class Utility_Exception_DECLSPEC SGException : std::exception
    {
      public:
        // 默认构造函数，用于创建一个没有错误信息的异常对象
        SGException ();

        // 构造函数，用于初始化SGException对象，接受一个C风格字符串作为错误信息
        explicit SGException (const char* sMessage);
        // 带错误信息的构造函数，用于创建一个包含特定错误信息的异常对象
        explicit SGException (std::string sMessage);
        // 拷贝构造函数，用于创建一个与现有异常对象相同的异常对象
        SGException (const SGException& inst) noexcept;
        // 析构函数，默认实现，不抛出异常
        ~SGException () noexcept override = default;

        // 赋值操作符，用于将一个异常对象赋值给另一个异常对象
        SGException& operator= (const SGException& inst);

        // 返回异常描述信息的函数
        const char* what () const noexcept override;

        // 模板函数，用于向异常对象中添加流数据
        template <class StreamValueType>
        SGException& operator<< (StreamValueType const& rValue)
        {
            std::stringstream buffer;
            buffer << rValue;

            append_message (buffer.str ());

            return *this;
        }

        // 重载运算符<<，用于向异常对象中添加标准输出流操作符
        SGException& operator<< (std::ostream& (*pf) ( std::ostream& ) );

        // 重载运算符<<，用于向异常对象中添加C风格字符串
        SGException& operator<< (const char* rString);

        /// 将异常信息打印到指定的输出流上
        void print (std::ostream& rOStream) const;

      protected:
        // 返回异常的详细信息
        virtual std::string info () const;
        // 返回异常的消息
        virtual std::string message () const;
        // 返回异常的堆栈跟踪信息
        virtual std::string stacktrace () const;

      private:
        // 更新what()方法返回的字符串
        void update_what ();
        // 向异常消息中追加新的消息
        void append_message (const std::string& rMessage);

      protected:
        std::string myMessage;  // 存储异常消息
        std::string myWhat;     // 存储what()方法返回的字符串
    };

    // 定义输入流操作符重载函数，用于从输入流中读取SGException对象
    Utility_Exception_DECLSPEC std::istream& operator>> (std::istream& rIStream, SGException& rThis);

    // 定义输出流操作符重载函数，用于将SGException对象输出到输出流中
    Utility_Exception_DECLSPEC std::ostream& operator<< (std::ostream& rOStream, const SGException& rThis);

    // SGRuntimeError类，继承自SGException类，用于表示运行时错误。
    class Utility_Exception_DECLSPEC RuntimeError : public SGException
    {
      public:
        // 默认构造函数
        RuntimeError ();
        // 接受C风格字符串的构造函数
        explicit RuntimeError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit RuntimeError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~RuntimeError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };

    // TypeError类，继承自SGException类，用于表示类型错误。
    class Utility_Exception_DECLSPEC TypeError : public SGException
    {
      public:
        // 默认构造函数
        TypeError ();
        // 接受C风格字符串的构造函数
        explicit TypeError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit TypeError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~TypeError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };

    // ValueError类，继承自SGException类，用于表示值错误。
    class Utility_Exception_DECLSPEC ValueError : public SGException
    {
      public:
        // 默认构造函数
        ValueError ();
        // 接受C风格字符串的构造函数
        explicit ValueError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit ValueError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~ValueError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };

    // IndexError类，继承自SGException类，用于表示索引错误。
    class Utility_Exception_DECLSPEC IndexError : public SGException
    {
      public:
        // 默认构造函数
        IndexError ();
        // 接受C风格字符串的构造函数
        explicit IndexError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit IndexError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~IndexError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };

    // ImportError类，继承自SGException类，用于表示导入错误。
    class Utility_Exception_DECLSPEC ImportError : public SGException
    {
      public:
        // 默认构造函数
        ImportError ();
        // 接受C风格字符串的构造函数
        explicit ImportError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit ImportError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~ImportError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };

    // ParserError类，继承自SGException类，用于表示解析错误。
    class Utility_Exception_DECLSPEC ParserError : public SGException
    {
      public:
        // 默认构造函数
        ParserError ();
        // 接受C风格字符串的构造函数
        explicit ParserError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit ParserError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~ParserError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };

    // FileSystemError类，继承自SGException类，用于表示文件系统错误。
    class Utility_Exception_DECLSPEC FileSystemError : public SGException
    {
      public:
        // 默认构造函数
        FileSystemError ();
        // 接受C风格字符串的构造函数
        explicit FileSystemError (const char* sMessage);
        // 接受std::string类型字符串的构造函数
        explicit FileSystemError (const std::string& sMessage);

        // 析构函数，默认实现，不抛出异常
        ~FileSystemError () noexcept override = default;

      protected:
        // 返回错误信息的虚函数
        std::string info () const override;
    };
}  // namespace SG::Utility
